package Servlets.xzh;


import Bean.Product;
import Bean.property.FlowTrendDTO;
import Bean.property.PurchasePieDTO;
import Bean.property.RemarkPieDTO;
import Bean.property.ZhuZhuangDTO;
import Util.GokJDBCUtil2;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;
import java.time.LocalDate;

@Slf4j
@WebServlet(name = "FinancialStatements" ,value = "/FinancialStatements")
public class PropertyFinancialStatementsServlet extends HttpServlet {
    public void init() {
    }

    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
        // 1. 获取参数
        String startDate = req.getParameter("startDate");
        String endDate = req.getParameter("endDate");

        //  如果没有选择时间段，默认最近7天
        if ((startDate == null || startDate.isEmpty()) || (endDate == null || endDate.isEmpty())) {
            java.time.LocalDate today = java.time.LocalDate.now();
            java.time.LocalDate weekAgo = today.minusDays(21); // 包含今天共21天
            startDate = weekAgo.toString();
            endDate = today.toString();
        }
        //---------------------1.flowTrend----------------------------
        String sql_income = "select Date(incometime) as day ,sum(money) as total from income where incometime between ? and ? group by incometime";
        Map<String,Double> incomeMap = GokJDBCUtil2.queryForDayMoneyMap(sql_income,startDate, endDate);
        List<String> dateList = getDateList(startDate, endDate);
        for (String date : dateList) {
            if (!incomeMap.containsKey(date)) {
                incomeMap.put(date, 0.0);
            }
        }
        String sql_expense = "select Date(paymenttime) as day ,sum(money) as total from expense where paymenttime between ? and ? group by paymenttime";
        Map<String,Double> expenseMap = GokJDBCUtil2.queryForDayMoneyMap(sql_expense,startDate, endDate);
        List<String> dateList2 = getDateList(startDate, endDate);
        for (String date : dateList2) {
            if (!expenseMap.containsKey(date)) {
                expenseMap.put(date, 0.0);
            }
        }
        // 按日期顺序组装收入和支出列表
        List<Double> incomeList = new ArrayList<>();
        List<Double> payList = new ArrayList<>();
        for (String date : dateList) {
            incomeList.add(incomeMap.getOrDefault(date, 0.0));
            payList.add(expenseMap.getOrDefault(date, 0.0));
        }
        // 封装到DTO
        FlowTrendDTO flowTrend = new FlowTrendDTO();
        flowTrend.setDateList(dateList);
        flowTrend.setIncomeList(incomeList);
        flowTrend.setPayList(payList);
        //--------------------------2.purchasePie-----------------------
        List<PurchasePieDTO> purchasePieList = new ArrayList<>();
        StringBuilder sql_purchase = new StringBuilder("SELECT remark AS day, SUM(money) AS total FROM expense WHERE isdeleted=0 ");
        List<Object> params = new ArrayList<>();

        if(!startDate.isEmpty()){
            sql_purchase.append(" AND  paymenttime > ?");
            params.add(startDate);
        }
        if(!endDate.isEmpty()){
            sql_purchase.append(" AND  paymenttime < ?");
            params.add(endDate);
        }
        sql_purchase.append(" GROUP BY day");
        Map<String, Double> rows = GokJDBCUtil2.queryForDayMoneyMap(sql_purchase.toString(), params.toArray());
        for(Map.Entry<String, Double> entry : rows.entrySet()) {
            PurchasePieDTO purchasePieDTO = new PurchasePieDTO();
            purchasePieDTO.setName(entry.getKey());
            purchasePieDTO.setValue(entry.getValue());
            purchasePieList.add(purchasePieDTO);
        }
        //--------------------------3.reamrkPie-----------------------
        List<RemarkPieDTO> remarkPieList = new ArrayList<>();
        StringBuilder sql_remark = new StringBuilder("SELECT remark AS day, SUM(money) AS total FROM income WHERE isdeleted=0");
        List<Object> params_remark = new ArrayList<>();

        if(!startDate.isEmpty()){
            sql_remark.append(" AND  incometime > ?");
            params_remark.add(startDate);
        }
        if(!endDate.isEmpty()){
            sql_remark.append(" AND  incometime < ?");
            params_remark.add(endDate);
        }
        sql_remark.append(" GROUP BY day");
        Map<String, Double> rows_remark = GokJDBCUtil2.queryForDayMoneyMap(sql_remark.toString(), params_remark.toArray());
        for(Map.Entry<String, Double> entry : rows_remark.entrySet()) {
            remarkPieList.add(new RemarkPieDTO(entry.getKey(), entry.getValue()));
        }
        //--------------------------柱状图----------------------------
        StringBuilder sql_expense_size = new StringBuilder("select remark as day,SUM(money) as total from expense where isdeleted=0");
        StringBuilder sql_income_size = new StringBuilder("select remark as day,SUM(money) as total from income where isdeleted=0");
        List<Object> params_zhu = new ArrayList<>();
        if(!startDate.isEmpty()){
            sql_expense_size.append(" AND paymenttime > ?");
            sql_income_size.append(" AND  incometime > ?");
            params_zhu.add(startDate);
        }
        if(!endDate.isEmpty()){
            sql_expense_size.append(" AND paymenttime < ?");
            sql_income_size.append(" AND  incometime < ?");
            params_zhu.add(endDate);
        }
        sql_expense_size.append(" GROUP BY remark");
        sql_income_size.append(" GROUP BY remark");
        Map<String, Double> incomes= GokJDBCUtil2.queryForDayMoneyMap(sql_income_size.toString(), params.toArray());
        Map<String, Double> expenses = GokJDBCUtil2.queryForDayMoneyMap(sql_expense_size.toString(), params.toArray());
        //所有茶全集
        Set<String> allTeaNames = new HashSet<>();
        allTeaNames.addAll(incomes.keySet());
        allTeaNames.addAll(expenses.keySet());
        //x轴y轴
        List<String> teasList = new ArrayList<>();
        List<Double> incomesList = new ArrayList<>();
        List<Double> expensesList = new ArrayList<>();

        for (String tea : allTeaNames) {
            Double income = incomes.getOrDefault(tea, 0.0);
            Double expense = expenses.getOrDefault(tea, 0.0);

            teasList.add(tea);
            incomesList.add(income);
            expensesList.add(expense);

        }
        log.info("tea:"+teasList);
        log.info("income:"+incomesList);
        log.info("expense:"+expensesList);
        ZhuZhuangDTO z = new ZhuZhuangDTO(teasList, incomesList, expensesList);

        // 4. 传递到页面
        req.setAttribute("startDate", startDate);
        req.setAttribute("endDate", endDate);
        req.setAttribute("flowTrend", flowTrend);
        req.setAttribute("remarkOption",remarkPieList);
        req.setAttribute("purchaseOption",purchasePieList);
        req.setAttribute("expenseincomeOption",z);


        // 5. 跳转到JSP
        req.getRequestDispatcher("/pages/property_manage/property_manage_reports.jsp").forward(req, res);
    }
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
        String method = req.getMethod();
        try {
            if (method.equals("GET")) {
                this.doGet(req, res);
            }else {
                PrintWriter writer = res.getWriter();
                writer.println("{\"code\":\"400\",\"msg\":\"此方法不允许\"}");
                writer.close();
            }
        } catch (Exception e) {
            log.error("服务器处理请求时发生错误", e);
            PrintWriter writer = res.getWriter();
            writer.println("{\"code\":\"500\",\"msg\":\"服务器处理请求时发生错误\"}");
            writer.close();
        }
    }
    public void destroy() {
    }
        // 获取时间段内所有日期
    public List<String> getDateList(String start, String end) {
        List<String> list = new ArrayList<>();
        LocalDate s = LocalDate.parse(start);
        LocalDate e = LocalDate.parse(end);
        while (!s.isAfter(e)) {
            list.add(s.toString());
            s = s.plusDays(1);
        }
        return list;
    }
}
